package org.mte.sak.mail;

import java.util.ArrayList;
import java.util.Date;
import java.util.Properties;

import javax.activation.DataHandler;
import javax.mail.Address;
import javax.mail.Authenticator;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.SendFailedException;
import javax.mail.Session;
import javax.mail.Transport;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeBodyPart;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeMultipart;

import org.mte.sak.file.FileObject;


/**
 * Gestisce l'invio e la ricezione di mail (Singleton).
 *
 * @author Marco Traversari
 * @version $Revision: 1.4 $ $Date: 2011-09-23 10:44:15 $
 */
public class MailManager {

	/**
	 * instanza
	 */
	private static MailManager instance = null;

	/**
	 * isDebug
	 */
	public static boolean isDebug = false;

	/**
	 * MailManager
	 */
	private MailManager() {
	}

	/**
	 * getInstance
	 * @return instance
	 */
	public static MailManager getInstance() {
		if (instance == null) {
			instance = new MailManager();
		}
		return instance;
	}

	/**
	 * setDebug
	 * @param isDebug
	 */
	public void setDebug(boolean isDebug) {
		MailManager.isDebug = isDebug;
	}

	/**
	 * send
	 * @param props
	 * @param mailMessage
	 * @throws Exception
	 */
	public void send(Properties props, MailMessage mailMessage) throws Exception {
		ArrayList<MailMessage> messages = new ArrayList<MailMessage>();
		messages.add(mailMessage);
		send(props, messages);
	}

	/**
	 * send
	 * @param props
	 * @param messages
	 * @throws Exception
	 */
	@SuppressWarnings("rawtypes")
	public void send(Properties props, ArrayList messages) throws Exception {
		if (props != null) {
			boolean isAuthentication = new Boolean(props.getProperty("mail.smtp.auth"));
			Session session = null;
			if (isAuthentication) {
				String username = props.getProperty("mail.smtp.user");
				String password = props.getProperty("mail.smtp.password");
				Authenticator authenticator = new MailAuthenticator(username, password);
				session = Session.getInstance(props, authenticator);
			} else {
				session = Session.getInstance(props, null);
			}
            String charset = props.getProperty("mail.mime.charset");
            if (charset != null) {
                System.setProperty("mail.mime.charset", charset);
            }
            int size = messages.size();
			for (int i = 0; i < size; i++) {
				MailMessage message = (MailMessage) messages.get(i);
				if (message.getTo() != null) {
					Message msg = new MimeMessage(session);
					msg.setRecipients(Message.RecipientType.TO,
											 InternetAddress.parse(message.getTo(), false));
					if (message.getFrom() != null &&
						!message.getFrom().equals("")) {
					   msg.setFrom(new InternetAddress(message.getFrom()));
					} else {
					   msg.setFrom(new InternetAddress(session.getProperty("mail.from")));
					}
					if (message.getCc() != null &&
						!message.getCc().equals("")) {
					   msg.setRecipients(Message.RecipientType.CC,
								   InternetAddress.parse(message.getCc(), false));
					}
					if (message.getBcc() != null &&
						!message.getBcc().equals("")) {
					   msg.setRecipients(Message.RecipientType.BCC,
								   InternetAddress.parse(message.getBcc(), false));
				   }
					msg.setSubject(message.getSubject());
					if (message.hasAttachment()) {
						MimeMultipart mimeMultipart = new MimeMultipart();
						MimeBodyPart mimeBodyPart = new MimeBodyPart();
						mimeBodyPart.setDisposition("inline");
						mimeBodyPart.setContent(buildHtmlCode(message), "text/html");
						mimeMultipart.addBodyPart(mimeBodyPart);
						MimeBodyPart filePart = null;
						for (int a = 0; a < message.getAttachments().size(); a++) {
							filePart = new MimeBodyPart();
							FileObject fileObject = message.getAttachment(a);
							DataHandler dataHandler = new DataHandler(new MailDataSource(fileObject.getContent()));
							filePart.setFileName(fileObject.getName());
							filePart.setDisposition("attachment");
							filePart.setDescription("Attached file: " + fileObject.getName());
							filePart.setDataHandler(dataHandler);
							mimeMultipart.addBodyPart(filePart);
						}
						msg.setContent(mimeMultipart);
					} else {
						if (message.getBody().indexOf("<") != -1) {
							msg.setContent(buildHtmlCode(message), "text/html");
						} else {
							msg.setText(message.getBody());
						}
					}
					msg.setHeader("X-Mailer", "JavaMail API");
					msg.setHeader("Reply-To", message.getFrom());
					msg.setSentDate(new Date());
					try {
						Transport.send(msg);
					} catch (SendFailedException e) {
						e.printStackTrace();
						String errorMessage = "";
						Address[] a0 = e.getInvalidAddresses();
						if (a0 != null) {
							for (Address a: a0) {
								errorMessage += a.toString() + ", ";
							}
						}
						int len = errorMessage.length();
						errorMessage = (len > 1) ? errorMessage.substring(0, len - 2) : null;
						if (errorMessage != null) {
							errorMessage = "Invalid Addresses: " + errorMessage;
						} else {
							errorMessage = e.getMessage();
						}
						throw new Exception(errorMessage);
					} catch (MessagingException me) {
						throw me;
					}
				}
			}
		}
	}

	/**
	 * Aggiunge i tags HTML base ad un messaggio.
	 *
	 * @param message
	 *
	 * @return message con tag HTML.
	 */
	private String buildHtmlCode(MailMessage message) {
		StringBuffer sb = new StringBuffer();
		sb.append("<html>\n");
		sb.append("<head><title>");
		sb.append(message.getSubject());
		sb.append("</title></head>\n");
		sb.append("<body>\n");
		sb.append(message.getBody());
		sb.append("\n</body>\n");
		sb.append("</html>\n");
		return sb.toString();
	}
}